package cn.yqn.service.impl;

import cn.yqn.doc.CourseDoc;
import cn.yqn.domain.*;
import cn.yqn.dto.CourseDto;
import cn.yqn.enums.GlobalEnumCode;
import cn.yqn.feign.CourseEsFeignClient;
import cn.yqn.feign.MeidaFileFeignClient;
import cn.yqn.mapper.CourseMapper;
import cn.yqn.mapper.CourseTypeMapper;
import cn.yqn.result.JSONResult;
import cn.yqn.service.*;
import cn.yqn.util.AssertUtil;
import cn.yqn.vo.CourseInfoVo;
import cn.yqn.vo.OrderInfoVo;
import cn.yqn.vo.OrderItemInfoVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author director
 * @since 2022-09-02
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private ITeacherService teacherService;

    @Autowired
    private ICourseDetailService courseDetailService;

    @Autowired
    private ICourseResourceService courseResourceService;

    @Autowired
    private ICourseMarketService courseMarketService;

    @Autowired
    private ICourseSummaryService courseSummaryService;

    @Autowired
    private CourseEsFeignClient courseEsFeignClient;

    @Autowired
    private CourseTypeMapper courseTypeMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private ICourseTeacherService courseTeacherService;

    @Autowired
    private ICourseChapterService  courseChapterService;

    @Autowired
    private MeidaFileFeignClient meidaFileFeignClient;

    @Autowired
    private ICourseUserLearnService courseUserLearnService;


    /**
    * @Title: 新增课程业务
    * @Description: TODO
    * @Author: YQN
    * @Version: 1.0
    * @Date:  2022/9/5 0:54  
    * @Parameters: [courseDto]
    * @Return void
    */
    @Override
    @Transactional
    public void save(CourseDto courseDto) {
        // dto获取对象
        Course course = courseDto.getCourse();
        CourseResource courseResource = courseDto.getCourseResource();
        CourseDetail courseDetail = courseDto.getCourseDetail();
        CourseMarket courseMarket = courseDto.getCourseMarket();
        List<Long> teacherIds = courseDto.getTeacherIds();
        // 1.判断新增课程是否有值
        isCourseExisted(course);        
        // 2.不存在添加课程,使用引用传递,同时操作一个对象
        saveCourse(course, teacherIds);
        // 3.保存字段信息
        saveCourseResourse(course, courseResource);
        saveCourseDetail(course, courseDetail);
        saveCourseMarket(course, courseMarket);
        initCourseSummary(course);
        saveCourseTeacher(course, teacherIds);
        // 课程类型加一
        courseTypeMapper.updateTotalCountById(course.getCourseTypeId());
    }

    @Override
    public void onLineCourse(Long courseId) {
        // 判断参数是否为空
        AssertUtil.isNotNull(courseId, GlobalEnumCode.PARAM_IS_NULL_ERROR);
        // 查询ID效验
        Course course = selectById(courseId);
        // 判断是否有内容
        AssertUtil.isNotNull(course, GlobalEnumCode.PARAM_IS_NULL_ERROR);
        // 查询课程上下架状态
        boolean Status = course.getStatus() == Course.STATUS_OFFLINE;
        AssertUtil.isTrue(Status, GlobalEnumCode.COURSE_EXISTED_ERROR2);
        // 设置课程上架状态
        course.setStatus(Course.STATUS_ONLINE);
        // 设置课程开启时间
        course.setOnlineTime(new Date());
        // 修改对象参数
        updateById(course);
        // Feign调用search保存参数到es
        CourseDoc courseDoc = new CourseDoc();
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        BeanUtils.copyProperties(course,courseDoc);
        BeanUtils.copyProperties(courseMarket,courseDoc);
        BeanUtils.copyProperties(courseSummary,courseDoc);
        //处理额外的参数
        courseDoc.setChargeName(courseMarket.getCharge().intValue() == 1 ? "收费":"免费");
        JSONResult jsonResult = courseEsFeignClient.saveCourseDoc(courseDoc);
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalEnumCode.valueOf("参数错误！"));

    }

    @Override
    public CourseInfoVo courseInfo(Long courseId) {
        // 根据课程ID查询 先校验参数
        AssertUtil.isNotNull(courseId, "课程Id不能为空");
        Course course = selectById(courseId);
        // 判断课程是否存在
        AssertUtil.isNotNull(course, "课程不纯在");
        // 查看课程是否是上架状态
        AssertUtil.isTrue(course.getStatus() == Course.STATUS_ONLINE, "课程状态不是上架状态！！！");
        // 然后根据课程Id查询每个表
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        // 先找课程
        // 查询老师表 因为一个课程可能对应多了老师字段 因为老师列表中又courseid
        EntityWrapper<CourseTeacher> EntityWrapper = new EntityWrapper<>();
        // 根据课程id查询老师
        EntityWrapper.eq("course_id", courseId);
        // 把条件放进查询中
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(EntityWrapper);
        // 遍历整个结果 将得到的流结果转换为List集合
        List<Long> collect = courseTeachers.stream().map(CourseTeacher::getTeacherId).collect(Collectors.toList());
        // 在找老师
        List<Teacher> teachers = teacherService.selectBatchIds(collect);

        // 查询课程章节
        List<CourseChapter> courseChapters = courseChapterService.listByCourseId(courseId);
        Map<Long, CourseChapter> courseChapterMap = courseChapters.stream()
                .collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        //1.为media微服务编写controller接口查询课程下视频
        //2.编写api-media,暴露Frign接口
        //3.依赖api-media,使用Feign远程调用查询课程下的视频信息
        JSONResult jsonResult = meidaFileFeignClient.queryMediasByCourserId(courseId);
        AssertUtil.isTrue(jsonResult.isSuccess(), "查询媒体信息失败！！");
        if (jsonResult.getData() != null) {//如果数据不为可空我们才处理
            List<MediaFile> mediaFiles = JSON.parseArray(jsonResult.getData().toString(), MediaFile.class);
            for (MediaFile mediaFile : mediaFiles) {
                mediaFile.setFileUrl("");
                CourseChapter courseChapter = courseChapterMap.get(mediaFile.getChapterId());
                if (courseChapter != null) {
                    courseChapter.getMediaFiles().add(mediaFile);
                }
            }
        }
        return new CourseInfoVo(course,courseDetail,courseSummary,courseMarket,courseChapters,teachers);
    }


    @Override
    public String getForUser(Long mediaId) {
        // 对参数校验
        AssertUtil.isNotNull(mediaId,"媒体id不能为空");
        // 通过feignd调用
        JSONResult jsonResult = meidaFileFeignClient.get(mediaId);
        AssertUtil.isTrue(jsonResult.isSuccess(),"媒体查询异常！！");
        AssertUtil.isNotNull(jsonResult.getData(),"媒体信息不存在！！");
        MediaFile mediaFile = JSON.parseObject(jsonResult.getData().toString(), MediaFile.class);
        if(mediaFile.getFree()){
            return mediaFile.getFileUrl();//免费的直接返回地址
        }
        // 3.根据mediaFile中的courseId查询当前登录人是否购买了课程 t_course_user_learn
        Long loginId = 3L;
        Wrapper<CourseUserLearn> wrapper = new EntityWrapper<>();
        wrapper.eq("login_id",loginId);
        wrapper.eq("course_id",mediaFile.getCourseId());
        CourseUserLearn courseUserLearn = courseUserLearnService.selectOne(wrapper);
        //   。否则提示：请购买课程后观看
        AssertUtil.isNotNull(courseUserLearn,"请购买后再观看！！");
        //   。购买了并且在客观看有效期，返回地址
        boolean before = new Date().before(courseUserLearn.getEndTime());
        AssertUtil.isTrue(before,"课程的可观看时间已经结束，尊贵的会员,请您为课程续费后方可观看！！");
        return mediaFile.getFileUrl();
    }

    /**
     * 订单数据
     * @param courseIds
     * 1.效验参数
     * 2.分隔courseIds
     * 3.批量查询Course
     * 4.业务判断
     *   。状态是否合法
     *   。course是否为空
     *   。课程的数量要和传递的课程Id数量一致
     *
     * 5.查找课程对应的销售信息
     * 6.讲课程信息+课程销售信息 封装成小Vo  OrderItemInfoVo
     * 7.当所有的小VO封装结束，还要封装大VO OrderInfoVo
     */
    @Override
    public OrderInfoVo orderinfo(String courseIds) {
        AssertUtil.isNotEmpty(courseIds, "未检测到课程Id!");
        String[] clurseIdArray = courseIds.split(",");
        List<Course> courses = selectBatchIds(Arrays.asList(clurseIdArray));
        AssertUtil.isTrue(clurseIdArray.length == courses.size(), "课程数不匹配!");
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        for (Course course : courses) {
            AssertUtil.isTrue(course.getStatus().intValue() == Course.STATUS_ONLINE,"课程状态非法！！！");
            CourseMarket courseMarket = courseMarketService.selectById(course.getId());
            OrderItemInfoVo orderItemInfo = new OrderItemInfoVo(course, courseMarket);
            orderInfoVo.getCourseInfos().add(orderItemInfo);
            orderInfoVo.setTotalAmount(orderInfoVo.getTotalAmount().add(courseMarket.getPrice()));
        }
        return orderInfoVo;
    }

    // 保存老师信息
    private void saveCourseTeacher(Course course, List<Long> teacherIds) {
        courseMapper.insertCourseTeacher(course.getId(), teacherIds);
    }

    // 初始化课程信息
    private void initCourseSummary(Course course) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);
    }

    // 课程营销信息
    private void saveCourseMarket(Course course, CourseMarket courseMarket) {
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);
    }

    // 详情信息
    private void saveCourseDetail(Course course, CourseDetail courseDetail) {
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);
    }

    // 资源信息
    private void saveCourseResourse(Course course, CourseResource courseResource) {
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);
    }

    private void saveCourse(Course course, List<Long> teacherIds) {
        course.setStatus(Course.STATUS_OFFLINE);
        // @TODO 以后做完登录之后过来获取当前登员工
        course.setLoginId(6L);
        course.setLoginUserName("yqn.cn");
        course.setChapterCount(Course.INIT_CHAPTER_COUNT);
            List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);
        String teacherNames = teachers.stream().map(Teacher::getName).collect(Collectors.joining(","));
        course.setTeacherNames(teacherNames);
        // 保存
        insert(course);
    }


    /**
        * @Title: 判断课程方法
        * @Description: TODO
        * @Author: YQN
        * @Version: 1.0
        * @Date:  2022/9/5 1:07  
        * @Parameters: [course]
        * @Return void
        */
    private void isCourseExisted(Course course) {
        // 封装的一个查询条件构造器,方便查询
        EntityWrapper<Course> wrapper = new EntityWrapper<>();
        // 查询对应字段获取值,接收数据
        wrapper.eq("name", course.getName());
        Course selectCourse = selectOne(wrapper);
        // 断言如果数据有重说明课程重复...非常巧妙
        AssertUtil.isNull(selectCourse, GlobalEnumCode.COURSE_EXISTED_ERROR);
    }
}
